import uuid
from typing import List

from sqlalchemy import text
from sqlalchemy.exc import SQLAlchemyError

from src.label import label_models as models
from src.config.database import db
from src.label import label_logger as logging
from src.label import label_schemas as schemas


def save_label(label_create: schemas.LabelCreate) -> str | None:
    """
    保存或更新标签信息到数据库。

    如果 label_create.id 存在且数据库中有对应记录，则更新该记录。
    否则，创建新记录。

    参数:
    label_create (LabelCreate): 包含要创建或更新标签的信息的 Pydantic 模型实例。

    返回:
    str | None: 成功时返回标签 ID，失败时返回 None。
    """
    try:
        # 校验 parent_label_id
        if not validate_parent_label(label_create.parent_label_id):
            logging.error(f"Invalid parent_label_id: {label_create.parent_label_id}")
            return None
        label_data = label_create.model_dump()
        label_id = label_data.get("id")
        if label_id is not None:
            # 查询是否已存在该 ID 的标签
            entity = db.query(models.Label).get(label_id)
            if entity:
                # 更新已有实体字段
                for key, value in label_data.items():
                    if key != "id" and hasattr(entity, key):
                        setattr(entity, key, value)
            else:
                # ID 不存在，可选择创建新实体（upsert 行为）
                label_data["id"] = str(uuid.uuid4())
                entity = models.Label(**label_data)
                db.add(entity)
        else:
            # 无 ID，创建新实体
            label_data["id"] = str(uuid.uuid4())
            entity = models.Label(**label_data)
            db.add(entity)
        db.commit()
        db.refresh(entity)
        return entity.id

    except SQLAlchemyError as e:
        db.rollback()
        logging.error(f"Error saving/updating label: {str(e)}")
        return None


def validate_parent_label(parent_label_id: str) -> bool:
    """
    校验父标签是否存在

    参数:
    parent_label_id: 父标签ID

    返回:
    bool: 存在返回True，否则返回False
    """
    if not parent_label_id:
        return True  # 空值表示没有父标签，是合法的

    parent_label = db.query(models.Label).filter(
        models.Label.id == parent_label_id
    ).first()

    return parent_label is not None


def get_all_labels() -> list[schemas.LabelRDTO]:
    """
    查询所有标签

    参数:
    - db: 数据库会话 (SQLAlchemy Session)

    返回:
    - list[models.Label]: 所有标签的列表
    """
    label_list = db.query(models.Label).all()
    if not label_list:
        return []
    return [schemas.LabelRDTO.model_validate(label) for label in label_list]


def get_label_by_id(label_id: str) -> schemas.LabelRDTO | None:
    """
    根据 ID 查询标签

    参数:
    - db: 数据库会话 (SQLAlchemy Session)
    - label_id: 标签 ID

    返回:
    - models.Label | None: 查询到的标签或 None
    """
    label = db.query(models.Label).filter(models.Label.id == label_id).first()
    return schemas.LabelRDTO.model_validate(label)


def get_label_by_code(label_code: str) -> schemas.LabelRDTO | None:
    """
    根据 label_code 查询标签

    参数:
    - db: 数据库会话 (SQLAlchemy Session)
    - label_code: 标签编码

    返回:
    - models.Label | None: 查询到的标签或 None
    """
    label = db.query(models.Label).filter(models.Label.label_code == label_code).first()
    return schemas.LabelRDTO.model_validate(label)


def get_labels_paginated(skip: int = 0, limit: int = 10) -> list[schemas.LabelRDTO]:
    """
    分页查询标签列表

    参数:
    - db: 数据库会话 (SQLAlchemy Session)
    - skip: 跳过多少条记录 (默认 0)
    - limit: 返回多少条记录 (默认 10)

    返回:
    - list[models.Label]: 分页后的标签列表
    """
    label_list = db.query(models.Label).offset(skip).limit(limit).all()
    return [schemas.LabelRDTO.model_validate(label) for label in label_list]


def validate_new_label_data(label_create_list: List[schemas.LabelCreate]):
    parent_id_list_to_be_checked = []
    code_list_to_be_checked = []
    key_list_to_be_checked = []

    for label_create in label_create_list:
        if label_create.parent_label_id:  # 修复逻辑错误：应该是 if 有值时才检查
            parent_id_list_to_be_checked.append(label_create.parent_label_id)
        if label_create.label_code:
            code_list_to_be_checked.append(label_create.label_code)
        if label_create.label_key:
            key_list_to_be_checked.append(label_create.label_key)

    # 检查 label_code 和 label_key 的唯一性
    if code_list_to_be_checked or key_list_to_be_checked:
        sql1 = f"SELECT id FROM label WHERE label_code IN ('{"','".join(code_list_to_be_checked)}') OR label_key IN ('{"','".join(key_list_to_be_checked)}')"
        logging.info(f"validate函数执行的sql1为：{sql1}")
        res1 = db.execute(text(sql1)).fetchall()  # 获取查询结果

        # 判断 res1 是否为空
        if res1:  # 如果 res1 不为空，说明存在重复的 label_code 或 label_key
            existing_ids = [row[0] for row in res1]
            raise ValueError(f"Duplicate label_code or label_key found with ids: {existing_ids}")

    # 检查 parent_label_id 是否存在
    if parent_id_list_to_be_checked:
        sql2 = f"SELECT id FROM label WHERE id IN ('{"','".join(parent_id_list_to_be_checked)}')"
        logging.info(f"validate函数执行的sql2为：{sql2}")
        res2 = db.execute(text(sql2)).fetchall()  # 获取查询结果

        # 判断是否存在缺失的 parent_label_id
        existing_parent_ids = [row[0] for row in res2]
        missing_parent_ids = set(parent_id_list_to_be_checked) - set(existing_parent_ids)
        if missing_parent_ids:
            raise ValueError(f"Parent labels not found: {missing_parent_ids}")

    return True


def save_labels_batch(label_creates: list[schemas.LabelCreate]) -> list[str] | None:
    """
    批量保新增标签信息到数据库。

    参数:
    label_creates (List[LabelCreate]): 包含要创建或更新标签的信息列表

    返回:
    list[str] | None: 成功时返回标签 ID 列表，失败时返回 None。
    """
    try:
        saved_ids = []
        # 先进行所有数据的校验
        validate_new_label_data(label_creates)
        # 执行批量保存
        for label_create in label_creates:
            label_data = label_create.model_dump()
            label_id = label_data.get("id")
            if label_id is not None:
                raise ValueError("ID cannot be None when creating a new label")
            label_data["id"] = str(uuid.uuid4())
            entity = models.Label(**label_data)
            db.add(entity)
            saved_ids.append(entity.id)
        db.commit()

        # 刷新所有实体获取最新数据
        for label_create in label_creates:
            label_id = label_create.id if label_create.id else saved_ids[
                len(saved_ids) - len(label_creates) + label_creates.index(label_create)]
            entity = db.query(models.Label).get(label_id)
            if entity:
                db.refresh(entity)

        return saved_ids

    except (SQLAlchemyError, ValueError) as e:
        db.rollback()
        logging.error(f"Error saving/updating labels batch: {str(e)}")
        return None


def get_labels_by_ids(label_ids: list[str]) -> list[schemas.LabelRDTO]:
    """
    根据 label_id 列表查询标签列表

    参数:
    - db: 数据库会话 (SQLAlchemy Session)
    - label_ids: 包含多个 label_id 的列表

    返回:
    - list[models.Label]: 查询到的标签列表
    """
    if not label_ids:
        return []
    label_list = db.query(models.Label).filter(models.Label.id.in_(label_ids)).all()
    return [schemas.LabelRDTO.model_validate(label) for label in label_list]
